package com.glodon.ggzy.core.dao;

import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;

import com.glodon.ggzy.core.model.Page;

/**
 * SimpleHibernateDao Dao的衍生接口
 * 
 * @param <T> DAO操作的对象类型
 * @param <PK> 主键类型
 * 
 * @author yangjf
 * @version 1.0
 *
 */
public interface ISimpleHibernateDao<T, PK> {

	/** 
	 * 保存新增或修改的对象
	 * @param entity
	 */
	public void save(final T entity);

	/**
	 * 删除对象.
	 * @param entity 对象必须是session中的对象或含id属性的transient对象.
	 */
	public void delete(final T entity);

	/**
	 * 删除对象根据ID
	 * @param id
	 */
	public void deleteById(final PK id);

	/**
	 * 按id获取对象.
	 * @param id 对象id
	 * @return 对象
	 */
	public T get(final PK id);

	/**
	 * 按id列表获取对象列表.
	 * @param ids 对象ID集合
	 * @return
	 */
	public List<T> get(final Collection<PK> ids);

	/**
	 * 获取全部对象.
	 * @return
	 */
	public List<T> getAll();

	/**
	 * 获取全部对象, 支持按属性行序.
	 * @param orderByProperty
	 * @param isAsc
	 * @return
	 */
	public List<T> getAll(String orderByProperty, boolean isAsc);

	/**
	 * 按属性查找对象列表, 匹配方式为相等.
	 * @param propertyName
	 * @param value
	 * @return
	 */
	public List<T> findBy(final String propertyName, final Object value);

	/**
	 * 按HQL查询对象列表.
	 * 
	 * @param <X>
	 * @param hql
	 * @param values 数量可变的参数,按顺序绑定.
	 * @return
	 */
	public <X> List<X> find(final String hql, final Object... values);

	/**
	 * 按HQL查询对象列表.
	 * 
	 * @param <X>
	 * @param hql
	 * @param values 命名参数,按名称绑定.
	 * @return
	 */
	public <X> List<X> find(final String hql, final Map<String, ?> values);

	/**
	 * 按HQL查询唯一对象.
	 * 
	 * @param <X>
	 * @param hql
	 * @param values 数量可变的参数,按顺序绑定.
	 * @return
	 */
	public <X> X findUnique(final String hql, final Object... values);

	/**
	 * 按HQL查询唯一对象.
	 * 
	 * @param <X>
	 * @param hql
	 * @param values 命名参数,按名称绑定.
	 * @return
	 */
	public <X> X findUnique(final String hql, final Map<String, ?> values);

	/**
	 * 执行HQL进行批量修改/删除操作.
	 * 
	 * @param hql
	 * @param values 数量可变的参数,按顺序绑定.
	 * @return 更新记录数.
	 */
	public int batchExecute(final String hql, final Object... values);

	/**
	 * 执行HQL进行批量修改/删除操作.
	 * 
	 * @param hql
	 * @param values 命名参数,按名称绑定.
	 * @return 更新记录数.
	 */
	public int batchExecute(final String hql, final Map<String, ?> values);

	/**
	 * 根据查询HQL与参数列表创建Query对象.
	 * 与find()函数可进行更加灵活的操作.
	 * 
	 * @param queryString
	 * @param values 数量可变的参数,按顺序绑定.
	 * @return
	 */
	public Query createQuery(final String queryString, final Object... values);

	/**
	 * 根据查询HQL与参数列表创建Query对象.
	 * 与find()函数可进行更加灵活的操作.
	 * 
	 * @param queryString
	 * @param values 命名参数,按名称绑定.
	 * @return
	 */
	public Query createQuery(final String queryString, final Map<String, ?> values);

	/**
	 * 按Criteria查询对象列表.
	 * 
	 * @param criterions 数量可变的Criterion.
	 * @return
	 */
	public List<T> find(final Criterion... criterions);

	/**
	 * 按Criteria查询唯一对象.
	 * 
	 * @param criterions 数量可变的Criterion.
	 * @return
	 */
	public T findUnique(final Criterion... criterions);

	/**
	 * 根据Criterion条件创建Criteria.
	 * 与find()函数可进行更加灵活的操作.
	 * 
	 * @param criterions 数量可变的Criterion.
	 * @return
	 */
	public Criteria createCriteria(final Criterion... criterions);

	/**
	 * 初始化对象.
	 * 使用load()方法得到的仅是对象Proxy, 在传到View层前需要进行初始化.
	 * 如果传入entity, 则只初始化entity的直接属性,但不会初始化延迟加载的关联集合和属性.
	 * 如需初始化关联属性,需执行:
	 * Hibernate.initialize(user.getRoles())，初始化User的直接属性和关联集合.
	 * Hibernate.initialize(user.getDescription())，初始化User的直接属性和延迟加载的Description属性.
	 * 
	 * @param proxy
	 */
	public void initProxyObject(Object proxy);

	/**
	 * Flush当前Session.
	 * 
	 */
	public void flush();

	/**
	 * 为Query添加distinct transformer.
	 * 预加载关联对象的HQL会引起主对象重复, 需要进行distinct处理.
	 * 
	 * @param query
	 * @return
	 */
	public Query distinct(Query query);

	/**
	 * 为Criteria添加distinct transformer.
	 * 预加载关联对象的HQL会引起主对象重复, 需要进行distinct处理.
	 * 
	 * @param criteria
	 * @return
	 */
	public Criteria distinct(Criteria criteria);

	/**
	 * 取得对象的主键名.
	 * 
	 * @return
	 */
	public String getIdName();

	/**
	 * 判断对象的属性值在数据库内是否唯一.
	 * 在修改对象的情景下,如果属性新修改的值(value)等于属性原来的值(orgValue)则不作比较.
	 * 
	 * @param propertyName
	 * @param newValue
	 * @param oldValue
	 * @return
	 */
	public boolean isPropertyUnique(final String propertyName, final Object newValue, final Object oldValue);

	/**
	 * 按DetachedCriteria获取所有实体集合  
	 *  
	 * @param criteria 数量可变的Criterion
	 * @return 集合
	 */
	public List<T> findByDetachedCriteria(DetachedCriteria detachedCriteria);

	/**
	 * 
	 * 根据分页集合根据参数
	 * 
	 * @param pageNumber
	 * @param pageSize
	 * @param values
	 * @return
	 */
	public Page getPageListByT(int pageNumber, int pageSize, Object[] values);

	/**
	 * 
	 * 根据Criteria查找TOP
	 * 
	 * @param detachedCriteria
	 * @return
	 */
	public List<T> findByDetachedCriteriaByTop(DetachedCriteria detachedCriteria);

	/**
	 * 
	 * 根据分页查询
	 * @param hql
	 * @param values
	 * @param countHql
	 * @param pageNumber
	 * @param pageSize
	 * @return
	 */
	public Page pageQuery(String hql, Object[] values, String countHql, int pageNumber, int pageSize);
	/**
	 * 不定参数查询
	 * @param paramsMap
	 * @param pageNumber
	 * @param pageSize
	 * @return
	 */
	public Page pageQuery(Map<String,Object> paramsMap, int pageNumber, int pageSize);
	
	/**
	 * 参数为map
	 * @param hql
	 * @param values
	 * @param countHql
	 * @param pageNumber
	 * @param pageSize
	 * @return
	 */
	public Page pageQuery(String hql, Map<String, Object> values, String countHql,	int pageNumber, int pageSize);
}
